#include "GameScene.h"
#include "CuttingPhotos.h"
#include "ConfigManager.h"
#include "LevelScene.h"
#include "PromptDialog.h"
#include <random>

USING_NS_CC;
using namespace ui;

Scene* GameScene::createScene(int chapter, int section, int row, int col)
{
    // 'scene' is an autorelease object
    auto scene = Scene::create();
    
    // 'layer' is an autorelease object
    auto layer = GameScene::create(chapter, section, row, col);

    // add layer as a child to scene
    scene->addChild(layer);

    // return the scene
    return scene;
}

GameScene* GameScene::create(int chapter, int section, int row, int col)
{
    GameScene *pRet = new(std::nothrow) GameScene();
    if (pRet && pRet->init(chapter, section, row, col))
    {
        pRet->autorelease();
        return pRet;
    }
    else
    {
        delete pRet;
        pRet = NULL;
        return NULL;
    }
}

// on "init" you need to initialize your instance
bool GameScene::init(int chapter, int section, int row, int col)
{
    //////////////////////////////
    // 1. super init first
    if ( !Layer::init() )
    {
        return false;
    }
    
    Size visibleSize = Director::getInstance()->getVisibleSize();
    Vec2 origin = Director::getInstance()->getVisibleOrigin();

    _chapter = chapter;
    _section = section;
    char buffer[20];
    sprintf(buffer, "%d_%d.png", _chapter, _section);
    _photoName = buffer;
    _timeCount = 0;
    _isWin = false;
    _isPause = false;
    _isShowing = false;
    _isMenuActioning = false;
    _isMenuShow = false;
    std::uniform_int_distribution<unsigned> u(0,5);
    std::default_random_engine e;
    e.seed((unsigned)time(NULL));
    _decorationIndex = u(e);
    
    auto bk = Sprite::create("game.png");
    bk->setAnchorPoint(Vec2(1, 0.5));
    bk->setPosition(Vec2(visibleSize.width, visibleSize.height/2));
    bk->setScale(getRealScale(bk->getContentSize().width));
    this->addChild(bk);
    
    _photo = CuttingPhotos::create(_photoName, row, col);
    auto photoSize = _photo->getContentSize();
    _photo->setPosition(origin.x + photoSize.width/2 + 50,
                       origin.y + visibleSize.height/2);
    this->addChild(_photo);
    
    sprintf(buffer, "decoration_%d.png", _decorationIndex);
    _decoration = Sprite::create(buffer);
    _decoration->setPosition(_photo->getPosition());
    this->addChild(_decoration);
    
    // Create the buttons
    _buttonScore = Button::create("score_normal.png", "score_normal.png");
    _buttonScore->setAnchorPoint(Vec2(1,0.5));
    _buttonScore->setTitleText("00:00:00");
    _buttonScore->setTitleFontSize(22);
    _buttonScore->setTitleColor(score_color);
    _buttonScore->setPosition(Vec2(visibleSize.width+30, visibleSize.height* 5/6));
    _buttonScore->setTouchEnabled(false);
    this->addChild(_buttonScore);
    
    _buttonReturn = Button::create("return_normal.png", "return_press.png");
    _buttonReturn->setAnchorPoint(Vec2(1,0.5));
    _buttonReturn->setTitleText("返回关卡");
    _buttonReturn->setTitleFontSize(25);
    _buttonReturn->setTitleColor(return_color);
    _buttonReturn->setPosition(Vec2(visibleSize.width+330, visibleSize.height* 4/6));
    _buttonReturn->addTouchEventListener(CC_CALLBACK_2(GameScene::touchEvent_return, this));
    this->addChild(_buttonReturn);
    
    _buttonOrigin = Button::create("origin_normal.png", "origin_press.png");
    _buttonOrigin->setAnchorPoint(Vec2(1,0.5));
    _buttonOrigin->setTitleText("查看原图");
    _buttonOrigin->setTitleFontSize(25);
    _buttonOrigin->setTitleColor(origin_color);
    _buttonOrigin->setPosition(Vec2(visibleSize.width+330, visibleSize.height* 3/6));
    _buttonOrigin->addTouchEventListener(CC_CALLBACK_2(GameScene::touchEvent_look, this));
    this->addChild(_buttonOrigin);
    
    _buttonRestart = Button::create("restart_normal.png", "restart_press.png");
    _buttonRestart->setAnchorPoint(Vec2(1,0.5));
    _buttonRestart->setTitleText("重新开始");
    _buttonRestart->setTitleFontSize(25);
    _buttonRestart->setTitleColor(restart_color);
    _buttonRestart->setPosition(Vec2(visibleSize.width+330, visibleSize.height* 2/6));
    _buttonRestart->addTouchEventListener(CC_CALLBACK_2(GameScene::touchEvent_restart, this));
    this->addChild(_buttonRestart);
    
    _buttonShare = Button::create("share_normal.png", "share_press.png");
    _buttonShare->setAnchorPoint(Vec2(1,0.5));
    _buttonShare->setTitleText("分享好友");
    _buttonShare->setTitleFontSize(25);
    _buttonShare->setTitleColor(share_color);
    _buttonShare->setPosition(Vec2(visibleSize.width+330, visibleSize.height* 1/6));
    _buttonShare->addTouchEventListener(CC_CALLBACK_2(GameScene::touchEvent_share, this));
    this->addChild(_buttonShare);
    
    this->schedule(schedule_selector(GameScene::timeCount_update), 1);
    
    initCustomEventListener();
    
    initTouchEventlistener();
    
    return true;
}

void GameScene::touchEvent_return(Ref *pSender, Widget::TouchEventType type){
    if(_isShowing) return;
    switch (type)
    {
        case Widget::TouchEventType::BEGAN:
            static_cast<Button*>(pSender)->setTitleColor(Color3B::WHITE);
            break;
            
        case Widget::TouchEventType::MOVED:
            break;
            
        case Widget::TouchEventType::ENDED:
            {
                static_cast<Button*>(pSender)->setTitleColor(return_color);
                AUDIOENGINE_PLAY_BUTTON_FX;
                _isPause = true;
                _isShowing = true;
                _photo->setEnabled(false);
                DialogEntry de = DialogEntry::RETURN;
                this->addChild(PromptDialog::create(de));
            }
            break;
            
        case Widget::TouchEventType::CANCELED:
            static_cast<Button*>(pSender)->setTitleColor(return_color);
            break;
            
        default:
            break;
    }
}

void GameScene::touchEvent_look(Ref *pSender, Widget::TouchEventType type){
    if(_isShowing) return;
    switch (type)
    {
        case Widget::TouchEventType::BEGAN:
            static_cast<Button*>(pSender)->setTitleColor(Color3B::WHITE);
            AUDIOENGINE_PLAY_BUTTON_FX;
            _preview = PreviewLayer::create(_photoName, _decorationIndex);
            if(_preview){
                this->addChild(_preview);
            }
            break;
            
        case Widget::TouchEventType::MOVED:
            break;
            
        case Widget::TouchEventType::ENDED:
            static_cast<Button*>(pSender)->setTitleColor(origin_color);
            if(_preview){
                _preview->destroy();
                _preview = nullptr;
            }
            break;
            
        case Widget::TouchEventType::CANCELED:
            static_cast<Button*>(pSender)->setTitleColor(origin_color);
            if(_preview){
                _preview->destroy();
                _preview = nullptr;
            }
            break;
            
        default:
            break;
    }
}

void GameScene::touchEvent_restart(Ref *pSender, Widget::TouchEventType type){
    if(_isShowing) return;
    switch (type)
    {
        case Widget::TouchEventType::BEGAN:
            static_cast<Button*>(pSender)->setTitleColor(Color3B::WHITE);
            break;
            
        case Widget::TouchEventType::MOVED:
            break;
            
        case Widget::TouchEventType::ENDED:
            {
                static_cast<Button*>(pSender)->setTitleColor(restart_color);
                AUDIOENGINE_PLAY_BUTTON_FX;
                _isPause = true;
                _isShowing = true;
                _photo->setEnabled(false);
                DialogEntry de = DialogEntry::RESTART;
                this->addChild(PromptDialog::create(de));
            }
            break;
            
        case Widget::TouchEventType::CANCELED:
            static_cast<Button*>(pSender)->setTitleColor(restart_color);
            break;
            
        default:
            break;
    }
}

void GameScene::touchEvent_share(Ref *pSender, Widget::TouchEventType type){
    if(_isShowing) return;
    switch (type)
    {
        case Widget::TouchEventType::BEGAN:
            static_cast<Button*>(pSender)->setTitleColor(Color3B::WHITE);
            break;
            
        case Widget::TouchEventType::MOVED:
            break;
            
        case Widget::TouchEventType::ENDED:
            {
                static_cast<Button*>(pSender)->setTitleColor(share_color);
                AUDIOENGINE_PLAY_BUTTON_FX;
            }
            break;
            
        case Widget::TouchEventType::CANCELED:
            static_cast<Button*>(pSender)->setTitleColor(share_color);
            break;
            
        default:
            break;
    }
}

void GameScene::initTouchEventlistener()
{
    auto listener = EventListenerTouchOneByOne::create();
    
    listener->onTouchBegan = [=](Touch *touch,Event *event){
        if(!_isShowing)
        {
            auto locationInNode = _decoration->convertToNodeSpace(touch->getLocation());
            auto s = _decoration->getContentSize();
            auto rect = Rect(0, 0, s.width, s.height);
            
            if (!rect.containsPoint(locationInNode) && !_isMenuActioning)
            {
                if(!_isMenuShow){
                    _isMenuActioning = true;
                    showMenu();
                }else{
                    _isMenuActioning = true;
                    hideMenu();
                }
            }
        }
        return false;
    };
    _eventDispatcher->addEventListenerWithSceneGraphPriority(listener, _decoration);
}

void GameScene::initCustomEventListener()
{
    //win event.
    auto listener_win = EventListenerCustom::create("game_win", [=](EventCustom* event){
        if(!this->_isWin){
            AUDIOENGINE_PLAY_WIN_FX;
            int preTimeCount = ConfigManager::getInstance()->getConfig(_chapter, _section);
            if(preTimeCount == 0){
                ConfigManager::getInstance()->setConfig(_chapter, _section, _timeCount);
                _buttonScore->setTitleText("新纪录：" + _buttonScore->getTitleText());
            }
            else if(_timeCount<preTimeCount){
                ConfigManager::getInstance()->setConfig(_chapter, _section, _timeCount);
                _buttonScore->setTitleText("新纪录：" + _buttonScore->getTitleText());
            }
            else{
                _buttonScore->setTitleText("过关了：" + _buttonScore->getTitleText());
            }
            this->_isWin = true;
        }
    });
    _eventDispatcher->addEventListenerWithSceneGraphPriority(listener_win, this);
    
    //return event.
    auto listener_return = EventListenerCustom::create("game_return", [=](EventCustom* event){
       Director::getInstance()->replaceScene(TransitionFade::create(0.2, LevelScene::createScene(), Color3B(255,255,255)));
    });
    _eventDispatcher->addEventListenerWithSceneGraphPriority(listener_return, this);
    
    //restart event.
    auto listener_restart = EventListenerCustom::create("game_restart", [=](EventCustom* event){
        _photo->restartGame();
        _timeCount=0;
        _isWin = false;
        _isPause = false;
        _isShowing = false;
        _photo->setEnabled(true);
    });
    _eventDispatcher->addEventListenerWithSceneGraphPriority(listener_restart, this);
    
    //cancel event.
    auto listener_cancel = EventListenerCustom::create("game_cancel", [=](EventCustom* event){
        _isPause = false;
        _isShowing = false;
        _photo->setEnabled(true);
    });
    _eventDispatcher->addEventListenerWithSceneGraphPriority(listener_cancel, this);
    
}

void GameScene::showMenu()
{
    AUDIOENGINE_PLAY_BUTTON_FX;
    float movetime = 0.2;
    float delaytime = 0.1;
    _moveShow  = MoveBy::create(movetime, Vec2(-300,0));
    _moveShow->retain();
    this->runAction(Sequence::create(CallFunc::create([=](){_buttonReturn->runAction(_moveShow);}),
                                     DelayTime::create(delaytime),
                                     CallFunc::create([=](){_buttonOrigin->runAction(_moveShow->clone());}),
                                     DelayTime::create(delaytime),
                                     CallFunc::create([=](){_buttonRestart->runAction(_moveShow->clone());}),
                                     DelayTime::create(delaytime),
                                     CallFunc::create([=](){_buttonShare->runAction(_moveShow->clone());}),
                                     DelayTime::create(movetime),
                                     CallFunc::create([=](){_isMenuActioning = false;_isMenuShow = true;_moveShow->release();}),
                                     nullptr));
    
}

void GameScene::hideMenu()
{
    AUDIOENGINE_PLAY_BUTTON_FX;
    float movetime = 0.2;
    float delaytime = 0.1;
    _moveHide = MoveBy::create(movetime, Vec2(300,0));
    _moveHide->retain();
    this->runAction(Sequence::create(CallFunc::create([=](){_buttonReturn->runAction(_moveHide);}),
                                     DelayTime::create(delaytime),
                                     CallFunc::create([=](){_buttonOrigin->runAction(_moveHide->clone());}),
                                     DelayTime::create(delaytime),
                                     CallFunc::create([=](){_buttonRestart->runAction(_moveHide->clone());}),
                                     DelayTime::create(delaytime),
                                     CallFunc::create([=](){_buttonShare->runAction(_moveHide->clone());}),
                                     DelayTime::create(movetime),
                                     CallFunc::create([=](){_isMenuActioning = false;_isMenuShow = false;_moveHide->release();}),
                                     nullptr));
}

void GameScene::timeCount_update(float dt){
    if(!_isWin && !_isPause){
        _timeCount++;
        if(_timeCount<356400){
            _buttonScore->setTitleText(convertTimeFromIntToStr(_timeCount));
        }
    }
}

std::string GameScene::convertTimeFromIntToStr(int time){
    int hour = time/3600;
    int last = time%3600;
    int min = last/60;
    int sec = last%60;
    char buffer[20];
    sprintf(buffer, "%02d:%02d:%02d",hour,min,sec);
    std::string str(buffer);
    return str;
}

float GameScene::getRealScale(int picWidth)
{
    float scale = 0;
    Size visibleSize = Director::getInstance()->getVisibleSize();
    Size designSize = Director::getInstance()->getOpenGLView()->getDesignResolutionSize();
    float originScale = visibleSize.height/designSize.height;
    picWidth *= originScale;
    if(picWidth>visibleSize.width)
    {
        scale = 1;
    }
    else{
        scale = visibleSize.width/picWidth;
    }
    return scale;
}
